// Copyright 2008 web2me.dev
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package net.web2me.api.util.multiurl;

import java.util.ArrayList;
import java.util.List;

/**
 * Provides helpers methods to work with {@link MultiUrl}
 * @author web2me
 *
 */
public class MultiUrlUtil {
	
	/**
	 * Identifies a URL with a pattern and return the resulting URL's list.<br>
	 * The pattern starts when a opening bracket is found and ends when an ending bracket is found.<br>
	 * The pattern can be comma separated numbers, two numbers separated by a hyphen, or a mix of both.<br>
	 * In the first case, each number would be treated as is, picking them
	 * for resolving URL's.<br>
	 * <br>Example:
	 * <pre>
	 * http://somegallery.com/gallery.php?gid=[109,115,143]
	 * </pre>
	 * The resulting URL's list:
	 * <pre>
	 * http://somegallery.com/gallery.php?gid=109
	 * http://somegallery.com/gallery.php?gid=115
	 * http://somegallery.com/gallery.php?gid=143
	 * </pre>
	 * The second case, the numbers are used to calculate a range, going from the first one to the second one.
	 * <br>Example:
	 * <pre>
	 * http://somegallery.com/gallery.php?gid=[100-102]
	 * </pre>
	 * The resulting URL's list:
	 * <pre>
	 * http://somegallery.com/gallery.php?gid=100
	 * http://somegallery.com/gallery.php?gid=101
	 * http://somegallery.com/gallery.php?gid=102
	 * </pre>
	 * And there is also the possibility to combine both cases.
	 * <br>Example:
	 * <pre>
	 * http://somegallery.com/gallery.php?gid=[100-102,107-110,150-152]
	 * </pre>
	 * The resulting URL's list:
	 * <pre>
	 * http://somegallery.com/gallery.php?gid=100
	 * http://somegallery.com/gallery.php?gid=101
	 * http://somegallery.com/gallery.php?gid=102
	 * http://somegallery.com/gallery.php?gid=107
	 * http://somegallery.com/gallery.php?gid=108
	 * http://somegallery.com/gallery.php?gid=109
	 * http://somegallery.com/gallery.php?gid=110
	 * http://somegallery.com/gallery.php?gid=150
	 * http://somegallery.com/gallery.php?gid=151
	 * http://somegallery.com/gallery.php?gid=152
	 * </pre> 
	 * @param url The URL with a valid pattern or no pattern at all
	 * @return A MultiUrl list
	 * @throws Exception If an invalid patter is found
	 */
	public final static List<MultiUrl> getMultiUrls(String url) throws InvalidPatternException {
		if(url != null){
			int start = 0;
			int end = 0;
			
			MultiUrl multi = null;
			List<MultiUrl> multiUrls = new ArrayList<MultiUrl>();
			
			if((start = url.indexOf("[")) > -1){
				if((end = url.indexOf("]", start)) > -1){
					String pattern = url.substring(start, end + 1);
					
					// The comma has the priority
					
					if(pattern.indexOf(",") > -1){
						String[] items = pattern.split(",");
						
						for(String item: items){
							if(item.indexOf("-") > -1){
								// It's a range item
								multiUrls.addAll(parseRange(item, pattern, url));
							}else{
								multi = new MultiUrl();
								
								String bareUrl = url.replace(pattern, "$");
								String matchedPattern = item.replaceAll("\\D", "");
								
								multi.setUrl(bareUrl.replace("$", matchedPattern));
								multi.setMatchedPattern(matchedPattern);
								
								multiUrls.add(multi);
							}
						}
						
						return multiUrls;
					}else{
						if(pattern.indexOf("-") > -1 && pattern.indexOf(",") == -1){
							multiUrls.addAll(parseRange(pattern, pattern, url));
							
							return multiUrls;
						}else{
							throw new InvalidPatternException("The URL pattern must have a comma or a hyphen");
						}
					}
				}else{
					throw new InvalidPatternException("Couldn't find the ending pattern bracket ]");
				}
			}else{
				if((end = url.indexOf("]", start)) > -1){
					throw new InvalidPatternException("Couldn't find the starting pattern bracket [");
				}
				
				multiUrls.add(saveNonPatternUrl(url));
				
				return multiUrls;
			}
		}
		
		throw new InvalidPatternException("The URL cannot be null");
	}
	
	private static MultiUrl saveNonPatternUrl(String pattern){
		MultiUrl multi = new MultiUrl();
		
		multi.setUrl(pattern);
		multi.setMatchedPattern("");
		
		return multi;
	}
	
	private static List<MultiUrl> parseRange(String patternToParse, String fullPattern, String url) throws InvalidPatternException{
		int rangeFrom = 0;
		int rangeTo = 0;
		
		String[] ranges = patternToParse.split("-");
		
		try{
			rangeFrom = Integer.valueOf(ranges[0].replaceAll("\\D", ""));
			rangeTo = Integer.valueOf(ranges[1].replaceAll("\\D", ""));
			
			String bareUrl = url.replace(fullPattern, "$");
			int size = rangeTo - rangeFrom;
			
			List<MultiUrl> multiUrls = new ArrayList<MultiUrl>();
			MultiUrl multi = null;
			
			for(int i = 0, gid = rangeFrom; i <= size && gid <= rangeTo; i++, gid++){
				multi = new MultiUrl();
				multi.setUrl(bareUrl.replace("$", String.valueOf(gid)));
				multi.setMatchedPattern(String.valueOf(gid));
				
				multiUrls.add(multi);
			}
			
			return multiUrls;
		}catch(Exception e){
			throw new InvalidPatternException("An error occured parsing the range pattern", e);
		}
	}
}
